Except where otherwise noted, this content is Copyright (c) 2020, RTE and licensed under a CC-BY-4.0 license.

Network Investment

Welcome to this new tutorial. Off course Hadar is well designed to compute study for network adequacy. You can launch Hadar to compute adequacy for the next second or next year.

But Hadar can also be used like a asset investment tool. In this example, thanks to Hadar, we will make the best choice for renewable energy and network investment.

We have a small region, with metropole which doesn't produce anything, a nuclear plan and two small cities with production.

First step parse data with pandas (and plot them)

In [1]:
import numpy as np
import pandas as pd
import hadar as hd
import plotly.graph_objects as go

Input data

In [2]:
a = pd.read_csv('a.csv', index_col='date')
fig = go.Figure()
fig.add_traces(go.Scatter(x=a.index, y=a['consumption'], name='load'))
fig.add_traces(go.Scatter(x=a.index, y=a['gas'], name='gas'))
fig.update_layout(title_text='Node A', yaxis_title='MW')
In [3]:
b = pd.read_csv('b.csv', index_col='date')
fig = go.Figure()
fig.add_traces(go.Scatter(x=b.index, y=b['consumption'], name='load'))
fig.update_layout(title_text='Node B (only consumption)', yaxis_title='MW')
In [4]:
c = pd.read_csv('c.csv', index_col='date')
fig = go.Figure()
fig.add_traces(go.Scatter(x=c.index, y=c['nuclear'], name='load'))
fig.update_layout(title_text='Node C (only production)', yaxis_title='MW')
In [5]:
d = pd.read_csv('d.csv', index_col='date')
fig = go.Figure()
fig.add_traces(go.Scatter(x=d.index, y=d['consumption'], name='load'))
fig.add_traces(go.Scatter(x=d.index, y=d['eolien'], name='eolien'))
fig.update_layout(title_text='Node D', yaxis_title='MW')

Base Study

Next step, code this network with Hadar

In [6]:
line = 2000 # 2000 MW 
In [7]:
base = hd.Study(['a', 'b', 'c', 'd'], horizon=8760) \
    .add_on_node('a', data=hd.Consumption(name='load', cost=10**6, quantity=a['consumption'])) \
    .add_on_node('a', data=hd.Production(name='gas', cost=80, quantity=a['gas'])) \
    .add_link(src='a', dest='b', cost=5, quantity=line) \
\
    .add_on_node('b', data=hd.Consumption(name='load', cost=10**6, quantity=b['consumption'])) \
    .add_link(src='b', dest='c', cost=5, quantity=line) \
\
    .add_on_node('c', data=hd.Production(name='nuclear', cost=50, quantity=c['nuclear'])) \
    .add_link(src='c', dest='a', cost=5, quantity=line) \
    .add_link(src='c', dest='b', cost=10, quantity=line) \
    .add_link(src='c', dest='d', cost=10, quantity=line) \
\
    .add_on_node('d', data=hd.Consumption(name='load', cost=10**6, quantity=d['consumption'])) \
    .add_on_node('d', data=hd.Production(name='eolien', cost=20, quantity=d['eolien'])) \
    .add_link(src='d', dest='c', cost=10, quantity=line)
In [8]:
optimizer = hd.LPOptimizer()
In [9]:
def compute_cost(study):
    res = optimizer.solve(study)
    agg = hd.ResultAnalyzer(study=study, result=res)
    return sum([agg.get_cost(n).sum() for n in agg.nodes])
In [10]:
base_cost = compute_cost(base)
base_cost
Out[10]:
47490601867.5

Find best place for solar

An investissor want to build a solar park with solar cells. According to last last data meteo, he could except the amount of production from this park. (Solar radiation is the same on each node of network).

What is the best node to install these solar pans ? (B is excluded because there are not enough space)

In [11]:
park = pd.read_csv('solar.csv', index_col='date')
fig = go.Figure()
fig.add_traces(go.Scatter(x=park.index, y=park['solar'], name='solar'))
fig.update_layout(title_text='Forecast Solar Park Power', yaxis_title='MW')
In [12]:
solar = hd.Production(name='solar', cost=10, quantity=park.values.flatten())
In [13]:
from copy import deepcopy
In [14]:
costs = pd.Series(data=[0, 0, 0], name='cost', index=['a', 'c', 'd'])

We use start three studies one for each node.

In [15]:
for node in costs.index:
    print('Start', node,' ', end='')
    study = deepcopy(base)
    study.add_on_node(node, data=solar)
    costs[node] = compute_cost(study)
    print('OK')
Start a  OK
Start c  OK
Start d  OK

% of cost evolution

In [16]:
(base_cost - costs) / base_cost * 100
Out[16]:
a    7.855833
c    1.935919
d    2.358194
Name: cost, dtype: float64

As we can see, network is more efficient if solar park is installed one node A (7.8% more efficient than only 2% for other node)

Find best place with on more line

Add an extra difficulties ! Region want to invest in a new line between A->C, D->B, A->D, D->A.

In this case, What is the best place to install solar park and what is the more usefull line to build ?

In [17]:
costs2 = pd.DataFrame(data={'a->c': [0, 0, 0], 'd->b': [0, 0, 0], 'a->d': [0, 0, 0], 'd->a': [0, 0, 0]},
                    index=['a', 'c', 'd'])
In [18]:
for node in costs2.index:
    for border in costs2.columns:
        print('Start', node, border, end=' ')
        study =deepcopy(base)
        study.add_on_node(node, data=solar)
        study.add_link(src=border[0], dest=border[-1], cost=10, quantity=line)
        costs2[border][node] = compute_cost(study)
        print('OK')
Start a a->c OK
Start a d->b OK
Start a a->d OK
Start a d->a OK
Start c a->c OK
Start c d->b OK
Start c a->d OK
Start c d->a OK
Start d a->c OK
Start d d->b OK
Start d a->d OK
Start d d->a OK

% of cost evolution

In [19]:
(base_cost - costs2) / base_cost * 100
Out[19]:
a->c d->b a->d d->a
a 7.855833 46.728266 8.760141 46.716781
c 1.935919 45.239082 2.758639 45.227437
d 2.358194 47.107628 2.884566 47.095729

Very interesting, new line is a game changer. D->A and D->B seem most valuable lines. If D->B is created, it's more efficient to install solar park on node D !

In [ ]: